<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>原型链</title>
</head>

<body>
    <h1>什么是原型链？</h1>
    <p>原型就是一个普通对象，它是为构造函数的实例共享属性和方法，所有实例中引用的原型都是同一个对象</p>
    <p>简单理解就是一个实例对象在调用属性和方法的时候，会依次从实例本身、构造函数原型、原型的原型上查找</p>
    <ul>
        <li>prototype 是用于创建实例对象的构造函数的属性，它主要用于存储构造函数的共享属性和方法。</li>
        <li>__proto__ 是用于访问对象的原型，它指向该对象的原型对象，用于实现原型链继承。</li>
    </ul>

    <h4>面试回答：我理解的原型链是一个普通对象，每个构造函数里面都有一个 prototype 属性，它用于声明属性和方法，prototype 就是原型。使用 __proto__
        访问对象的原型，这个称为链，如果说在自身找到了属性或者方法，则停止，否则一直向上查找直到为空对象，这个这个过程称为原型链。 </h4>

    <script>
        function Person() {
            this.say = function () {
                console.log('唱歌');
            }
            this.name = 'lee'
        }

        // 下面多次声明实例，每个方法都是独立的，会造成内存消耗。
        var p1 = new Person()
        var p2 = new Person()
        p1.say()
        p2.say()

        // 为了解决多次声明，JS 发明了 prototype 方法可以把方法挂在原型上，内存只保存一份，下面这段是解决方式
        Person.prototype.age = 29 // 定义一个属性
        Person.prototype.look = function () {
            console.log('西游记');
        }
        p1.look()
        p2.look()

        p1.name = 'tom'
        p1.age = 27

        // p1 实例利用 __proto__ 指向了 Person 构造函数。可以理解 __proto__ 是指针，实例对象中的数下
        console.log(p1.name, p1.age, '\n', p2.name, p2.age);

        console.log(p1.__proto__ === Person.prototype);
    </script>
</body>

</html>